#include "stdafx.h"
#include "ml_client.h"

ml_client::ml_client(char *client_id, char *client_key) {

	login_status = false;
    url_h = "http://mashedlife.com/api/ws.php?client=";
	int cs = strlen(client_id);

	id = (char *)malloc((cs+1) * sizeof(char));
	strcpy(id, client_id);
	id[cs] = 0;

	int ks = strlen(client_key);
    ckey = (char *)malloc((ks+1) * sizeof(char));
	strcpy(ckey, client_key);
	ckey[ks] = 0;

    session_id = (char *)malloc(30 * sizeof(char));
	session_key = (char *)malloc(70 * sizeof(char));
	status = (char *)malloc(30 * sizeof(char));
}

ml_client::~ml_client() {

    login_status = false;
	free(id);
	free(ckey);
	free(session_id);
	free(session_key);
	free(status);
       
}

char *ml_client::getSessionId() {
   return session_id;
}

char *ml_client::getSessionKey() {
   return session_key;
}

void ml_client::login(char *uname, char *pw) {

	string t1 = uname;
    string t2 = pw;
	string qs = "uname=" + t1 +"&pw=" + t2;
    aes.makeKey(ckey);
	string res = aes.aesAPIEncrypt(qs);
    
	char *a1 = (char *)malloc(res.size()+10*sizeof(char));

	UrlEncode(res.c_str(), a1, res.size()+10);

	string client_id = id;
	string url, k;

	for (int i=0; i<strlen(a1); i++)
	   k = k + (char) a1[i];
	
	free(a1);

	url = url_h + client_id + "&act=0&req=" +k;

    bool s = sendHTTP((char *)url.c_str());

	if (s) {
        string de_key;
		login_status = true;
		de_key = aes.aesAPIDecrypt(session_key);
		aes.makeKey((char *)de_key.c_str());
	}

 
}

void ml_client::addAccount(char *site, char *un, char *pw) {


	string t1 = site;
	string t2 = un;
	string t3 = pw;
	string qs = "dom=" + t1+ "&uname=" + t2 +"&pw=" + t3;

    string res = aes.aesAPIEncrypt(qs);

    char *a1 = (char *)malloc(res.size()+10*sizeof(char));

	UrlEncode(res.c_str(), a1, res.size()+10);

	string client_id = id;
	string url, j, k;

	for (int i=0; i<strlen(a1); i++)
	   k = k + (char) a1[i];
	
	free(a1);
	for (int i=0; i<strlen(session_id)-1; i++)
       j = j + (char) session_id[i];

	url = url_h + client_id + "&act=1&sess_id=" + j + "&req=" +k;
   
    bool s = sendHTTP((char *)url.c_str());

}

void ml_client::logout() {


    string qs = "logoff=1";
    string res = aes.aesAPIEncrypt(qs);

	string client_id = id;
	string url, k, j;
	
	char *a1 = (char *)malloc(res.size()+10*sizeof(char));
	UrlEncode(res.c_str(), a1, res.size()+10);

    for (int i=0; i<strlen(a1); i++)
	   k = k + (char) a1[i];
    free(a1);

    for (int i=0; i<strlen(session_id)-1; i++)
       j = j + (char) session_id[i];

	url = url_h + client_id + "&act=2&sess_id=" + j +"&req=" +k;
	
    bool s = sendHTTP((char *)url.c_str());

    if (s) login_status = false;
}

struct MemoryStruct {
    char *memory;
    size_t size;
};

static void *myrealloc(void *ptr, size_t size) {
   /* There might be a realloc() out there that doesn't like reallocing
       NULL pointers, so we take care of it here */
    if(ptr)
      return realloc(ptr, size);
    else
      return malloc(size);
}

static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) {
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)data;
  
    mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
    if (mem->memory) {
      memcpy(&(mem->memory[mem->size]), ptr, realsize);
      mem->size += realsize;
      mem->memory[mem->size] = 0;
    }
    return realsize;
}

void ml_client::parseResponse(char *res) {


	if (strstr(res,"sess_secret=") > 0) {
       size_t secret_s = strstr(res,"sess_secret=") - res + 12;
	   size_t secret_e = strstr(res,"sess_id=") - res;
	   
       strncpy(session_key, res + secret_s, secret_e - secret_s + 1);
       session_key[secret_e - secret_s] = 0;
	}

    if (strstr(res,"sess_id=") > 0) {

       size_t id_s = strstr(res,"sess_id=") - res + 8;
	   size_t id_e = strstr(res,"status=") - res;
    
       strncpy(session_id, res + id_s, id_e - id_s + 1);
       session_id[id_e - id_s] = 0;
	}

    size_t status_s = strstr(res,"status=") - res + 7;
    strncpy(status, res + status_s, strlen(res) - status_s);

}

bool ml_client::sendHTTP(char *url) {

    CURL *curl;
    CURLcode ccode;
    struct MemoryStruct chunk; 
    chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
    chunk.size = 0;    /* no data at this point */

    curl = curl_easy_init();
    if (curl) {
	   curl_easy_setopt(curl, CURLOPT_URL, url);
      //curl_easy_setopt(curl, CURLOPT_RETURNTRANSFER, 1);
       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
       curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

       ccode = curl_easy_perform(curl);

	   parseResponse(chunk.memory);

       curl_easy_cleanup(curl);
       if (strstr(status,"OK") > 0) return true;
	   else return false;
	}
	else return false;
}

int ml_client::UrlEncode(const char *source, char *dest, unsigned max) {
  static const char *digits = "0123456789ABCDEF";
  unsigned char ch;
  unsigned len = 0;
  char *start = dest;

  while (len < max - 4 && *source)
  {
    ch = (unsigned char)*source;
    if (*source == ' ') {
      *dest++ = '+';
    }
    else if (isalnum(ch) || strchr("-_.!~*'()", ch)) {
      *dest++ = *source;
    }
    else {
      *dest++ = '%';
      *dest++ = digits[(ch >> 4) & 0x0F];
      *dest++ = digits[       ch & 0x0F];
    }  
    source++;
  }
  *dest = 0;
  return start - dest;
}

int main(int argc, char *argv[]) {

	ml_client ml("3","Lw2znu1PofPGk0l/y0tEW5oJ3AQ=");

	if (argc == 6) {
         ml.login(argv[1],argv[2]);
	     ml.addAccount(argv[3] ,argv[4],argv[5]);
	     ml.logout();
	}
	else {
	     return -1;
	}

}